
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: CheckPair.java 135 2009-11-03 21:37:55Z archie.cobbs $
 */

package org.dellroad.sidekar.schema.model;

import java.util.HashSet;

/**
 * Used to avoid infinite loops during schema comparision.
 */
final class CheckPair {

    private static final ThreadLocal<HashSet<CheckPair>> CHECK_PAIRS = new ThreadLocal<HashSet<CheckPair>>();

    private final EntityModel entity1;
    private final EntityModel entity2;

    public CheckPair(EntityModel entity1, EntityModel entity2) {
        this.entity1 = entity1;
        this.entity2 = entity2;
    }

    public static void runWithChecks(Runnable runnable) {
        if (CHECK_PAIRS.get() != null)
            throw new IllegalStateException("already running with checks");
        CHECK_PAIRS.set(new HashSet<CheckPair>());
        try {
            runnable.run();
        } finally {
            CHECK_PAIRS.remove();
        }
    }

    public static void add(EntityModel entity1, EntityModel entity2) {
        if (CHECK_PAIRS.get() == null)
            return;
        CHECK_PAIRS.get().add(new CheckPair(entity1, entity2));
    }

    public static void remove(EntityModel entity1, EntityModel entity2) {
        if (CHECK_PAIRS.get() == null)
            return;
        CHECK_PAIRS.get().remove(new CheckPair(entity1, entity2));
    }

    public static boolean contains(EntityModel entity1, EntityModel entity2) {
        if (CHECK_PAIRS.get() == null)
            return false;
        return CHECK_PAIRS.get().contains(new CheckPair(entity1, entity2));
    }

    @Override
    public int hashCode() {
        return entity1.hashCode() ^ entity2.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || obj.getClass() != getClass())
            return false;
        CheckPair that = (CheckPair)obj;
        return (this.entity1 == that.entity1 && this.entity2 == that.entity2)
          || (this.entity1 == that.entity2 && this.entity2 == that.entity1);
    }
}

